import multer from 'multer';
import { Request, Router } from 'express';
import { RequestHandler } from 'express';
import { createError } from './errorHandler';

// 文件类型验证
const allowedMimeTypes = [
  // 图片
  'image/jpeg',
  'image/jpg', 
  'image/png',
  'image/gif',
  'image/webp',
  'image/svg+xml',
  // 文档
  'application/pdf',
  'application/msword',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  'application/vnd.ms-excel',
  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  'application/vnd.ms-powerpoint',
  'application/vnd.openxmlformats-officedocument.presentationml.presentation',
  // 压缩文件
  'application/zip',
  'application/x-rar-compressed',
  'application/x-7z-compressed',
  // 文本
  'text/plain',
  'text/csv',
  'application/json',
  // 音频
  'audio/mpeg',
  'audio/wav',
  'audio/ogg',
  // 视频
  'video/mp4',
  'video/mpeg',
  'video/quicktime',
  'video/x-msvideo'
];

// 文件过滤器
const fileFilter = (req: Request, file: Express.Multer.File, cb: multer.FileFilterCallback) => {
  // 检查文件类型
  if (!allowedMimeTypes.includes(file.mimetype)) {
    return cb(new Error(`不支持的文件类型: ${file.mimetype}`));
  }

  // 检查文件名（防止恶意文件名）
  const filename = file.originalname;
  if (!/^[a-zA-Z0-9._\-\u4e00-\u9fa5\s]+$/.test(filename)) {
    return cb(new Error('文件名包含非法字符'));
  }

  cb(null, true);
};

// 内存存储配置（文件存储在内存中，然后上传到OSS）
const storage = multer.memoryStorage();

// 基础multer配置
const baseConfig: multer.Options = {
  storage,
  fileFilter,
  limits: {
    fileSize: 100 * 1024 * 1024, // 100MB
    files: 10, // 最多10个文件
    fields: 20, // 最多20个字段
    fieldNameSize: 100, // 字段名最大长度
    fieldSize: 1024 * 1024 // 字段值最大长度1MB
  }
};

// 创建multer实例
const upload = multer(baseConfig);

// 单文件上传中间件
export const uploadSingle = (fieldName: string = 'file'): RequestHandler => {
  return upload.single(fieldName);
};

// 多文件上传中间件（单个字段多个文件）
export const uploadArray = (fieldName: string = 'files', maxCount: number = 10): RequestHandler => {
  return upload.array(fieldName, maxCount);
};

// 多文件上传中间件（多个字段）
export const uploadFields = (fields: { name: string; maxCount?: number }[]): RequestHandler => {
  return upload.fields(fields);
};

// 任意文件上传中间件
export const uploadAny = (): RequestHandler => {
  return upload.any();
};

// 仅处理表单数据（无文件）
export const uploadNone = (): RequestHandler => {
  return upload.none();
};

// 图片上传中间件（限制图片类型和大小）
export const uploadImage = (fieldName: string = 'image', maxSize: number = 10 * 1024 * 1024): RequestHandler => {
  const imageFilter = (req: Request, file: Express.Multer.File, cb: multer.FileFilterCallback) => {
    const imageTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];
    
    if (!imageTypes.includes(file.mimetype)) {
      return cb(new Error('只支持图片格式: JPEG, PNG, GIF, WebP'));
    }
    
    cb(null, true);
  };

  const imageUpload = multer({
    storage,
    fileFilter: imageFilter,
    limits: {
      fileSize: maxSize,
      files: 1
    }
  });

  return imageUpload.single(fieldName);
};

// 文档上传中间件
export const uploadDocument = (fieldName: string = 'document', maxSize: number = 50 * 1024 * 1024): RequestHandler => {
  const documentFilter = (req: Request, file: Express.Multer.File, cb: multer.FileFilterCallback) => {
    const documentTypes = [
      'application/pdf',
      'application/msword',
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      'application/vnd.ms-excel',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'application/vnd.ms-powerpoint',
      'application/vnd.openxmlformats-officedocument.presentationml.presentation',
      'text/plain',
      'text/csv'
    ];
    
    if (!documentTypes.includes(file.mimetype)) {
      return cb(new Error('只支持文档格式: PDF, Word, Excel, PowerPoint, TXT, CSV'));
    }
    
    cb(null, true);
  };

  const documentUpload = multer({
    storage,
    fileFilter: documentFilter,
    limits: {
      fileSize: maxSize,
      files: 1
    }
  });

  return documentUpload.single(fieldName);
};

// 错误处理中间件
export const handleUploadError = (error: any, req: Request, res: any, next: any): void => {
  if (error instanceof multer.MulterError) {
    switch (error.code) {
      case 'LIMIT_FILE_SIZE':
        return res.status(400).json({
          success: false,
          message: '文件大小超出限制'
        });
      case 'LIMIT_FILE_COUNT':
        return res.status(400).json({
          success: false,
          message: '文件数量超出限制'
        });
      case 'LIMIT_UNEXPECTED_FILE':
        return res.status(400).json({
          success: false,
          message: '意外的文件字段'
        });
      default:
        return res.status(400).json({
          success: false,
          message: `文件上传错误: ${error.message}`
        });
    }
  }

  if (error.message) {
    return res.status(400).json({
      success: false,
      message: error.message
    });
  }

  next(error);
};

const uploadMiddleware = {
  uploadSingle,
  uploadArray,
  uploadFields,
  uploadAny,
  uploadNone,
  uploadImage,
  uploadDocument,
  handleUploadError
};

export default uploadMiddleware;